# !/usr/bin/env python
# -*-coding:utf-8 -*-

"""
# Author     ：skyTree
# version    ：python 3.11
# Description：用户路由
"""
import math
import re

import openpyxl
from fastapi import APIRouter, Depends, HTTPException, Query, UploadFile, File, Security
from openpyxl import Workbook
from openpyxl.styles import Alignment, Font, Border, Side
from starlette.responses import FileResponse

from core.Response import base_response, base_detail_response
from core.Utils import check_password, hash_password
from curd.user import add_user_curd, edit_user_curd, get_permissions_list
from schemas.base import BaseResponse
from schemas.user import UserCreateSchema, UserOutSchema, UserEditSchema, UserResponseSchema, LoginSchema, \
    UserTokenSchema, UserListOutSchema, RoleSchema
from models.base import User, Role, Menu
from core.Auth import create_access_token, check_permissions
from typing import Union, List, Any

user_router = APIRouter(prefix='/users')


@user_router.post('/login', summary='登录', response_model=Union[UserTokenSchema, BaseResponse])
async def login(post: LoginSchema):
    username = post.username
    user = await User.get_or_none(name=username)
    if not user:
        return base_response(code=400, msg='用户不存在！')
    if not check_password(post.password, user.password):
        return base_response(code=400, msg='密码错误！')
    jwt_token = {
        'user_id': user.id,
        'user_name': user.name
    }
    token = create_access_token(jwt_token)
    data = {
        'token': token,
        'user': UserOutSchema(**dict(user), permissionsList=await get_permissions_list(user.id))
    }
    return base_response(code=200, msg='登录成功！', data=data)


@user_router.post('', summary='增加用户', response_model=Union[UserResponseSchema, BaseResponse])
async def user_add(user: UserCreateSchema):
    try:
        create_user = await add_user_curd(user)
    except HTTPException as e:
        return base_response(code=str(e).split(":")[0], msg=str(e).split(":")[1])
    except Exception as e:
        return base_response(code=500, msg=f'新增用户失败！错误原因为{e}')
    if not create_user:
        return base_response(code=400, msg='新增用户失败！')
    return base_response(code=200, msg='新增用户成功！', data=create_user)


@user_router.delete('/{id}', summary='删除用户', response_model=BaseResponse)
async def user_del(id: int):
    user = await User.get_or_none(id=id)
    if not user:
        return base_response(code=400, msg='用户不存在！')
    await user.roles.clear()
    await user.delete()
    await user.save()
    return base_response(code=200, msg='删除用户成功！')


@user_router.put('', summary='编辑用户', response_model=Union[UserResponseSchema, BaseResponse])
async def user_edit(user: UserEditSchema):
    try:
        edit_user = await edit_user_curd(user)
        return base_response(code=200, msg='编辑用户成功！', data=edit_user)
    except HTTPException as e:
        return base_response(code=str(e).split(":")[0], msg=str(e).split(":")[1])
    except Exception as e:
        return base_response(code=500, msg=f'编辑用户失败！错误原因为{e}')


@user_router.get('', summary='用户列表', response_model=UserListOutSchema)
async def user_list(page: int = 1, size: int = 10, name: str = None):
    if name:
        total = await User.filter(name__contains=name).all().count()
        users = await User.filter(name__contains=name).all().limit(size).offset(size * (page - 1)).prefetch_related(
            'roles')
        items = []
        for user in users:
            role_list = [RoleSchema(id=role.id, name=role.name, desc=role.desc) for role in await user.roles.all()]
            user_out_instance = UserOutSchema(**dict(user), role=role_list,
                                              permissionsList=await get_permissions_list(user.id))
            items.append(user_out_instance)
    else:
        total = await User.all().count()
        users = await User.all().limit(size).offset(size * (page - 1)).prefetch_related('roles')
        items = []
        for user in users:
            role_list = [RoleSchema(id=role.id, name=role.name, desc=role.desc) for role in await user.roles.all()]
            user_out_instance = UserOutSchema(**dict(user), role=role_list,
                                              permissionsList=await get_permissions_list(user.id))
            items.append(user_out_instance)
    data = {
        'total': total,
        'page': page,
        'pages': math.ceil(total / size),
        'data': items,
    }
    return base_response(code=200, msg='查询用户成功！', data=data)


@user_router.get('/{id}', summary='查询用户详情', response_model=Union[UserResponseSchema, BaseResponse])
async def user_detail(id: int):
    user = await User.get_or_none(id=id)
    if not user:
        return base_response(code=400, msg='用户不存在！')
    user_out = UserOutSchema(**dict(user), permissionsList=await get_permissions_list(user.id))
    return base_detail_response(code=200, msg='查询用户成功！', data=user_out)


@user_router.get('/reset/{id}', summary='重置密码', response_model=BaseResponse)
async def user_reset_password(id: int):
    user = await User.get_or_none(id=id)
    if not user:
        return base_response(code=400, msg='用户不存在！')
    user.password = hash_password('666666')
    await user.save()
    return base_response(code=200, msg='重置密码成功！')


@user_router.get('/export/all', summary='导出用户')
async def user_export(ids: str = Query(None)):
    if ids:
        products = await User.filter(id__in=eval(ids)).all().values()
    else:
        products = await User.all().values()
    wb = Workbook()
    ws = wb.active

    ws.sheet_properties.tabColor = "1072BA"
    # 设置表头样式
    header = ws.cell(row=1, column=1)
    header.value = '用户表'
    header.alignment = Alignment(horizontal='center', vertical='center')
    header.font = Font(bold=True, color='FF0000')
    ws.merge_cells(start_row=1, start_column=1, end_row=1, end_column=3)

    # 设置列宽
    ws.column_dimensions['A'].width = 20  # 设置第一列的宽度为20
    ws.column_dimensions['C'].width = 20  # 设置第一列的宽度为20
    # 设置列宽
    ws.row_dimensions[1].height = 50  # 设置第一行的高度为20

    # 写入数据
    ws.append(["姓名", "昵称", "手机号码"])
    for product in products:
        ws.append([product["name"], product["nick_name"], product["phone"]])

    # 添加边框
    for row in ws.iter_rows(min_row=1, max_row=ws.max_row, min_col=1, max_col=3):
        for cell in row:
            cell.border = Border(left=Side(style='thin'), right=Side(style='thin'), top=Side(style='thin'),
                                 bottom=Side(style='thin'))

    # 遍历所有列，设置列的对其方式
    for col in ws.columns:
        for cell in col:
            # 设置单元格的对齐方式
            cell.style = 'Pandas'
            cell.alignment = Alignment(horizontal='center', vertical='center')

    # 遍历所有行，包括空行，从第二行开始，因为第一行是标题
    for row_idx in range(2, ws.max_row + 1):
        # 设置行高
        ws.row_dimensions[row_idx].height = 30  # 设置行高为50

    file_path = "products.xlsx"
    wb.save(file_path)
    return FileResponse(file_path, filename="products.xlsx",
                        media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")


@user_router.post('/upload', summary='导入用户')
async def user_upload(file: UploadFile):
    # 检查文件类型是否为 Excel
    if not file.filename.endswith(('.xls', '.xlsx')):
        return base_response(code=400, msg='文件格式错误！')
    if file.size > 1024 * 1024 * 5:
        return base_response(code=400, msg='文件大小不能超过5MB！')

    # 读取 Excel 文件
    wb = openpyxl.load_workbook(file.file)
    ws = wb.active

    # 遍历 Excel 表格的每一行数据并保存到数据库中
    for row in ws.iter_rows(min_row=2, values_only=True):  # Assuming first row is header
        try:
            name, nick_name, phone, password = row
            # 数据校验
            if not name or not password:
                raise ValueError('姓名和密码不能为空！')
            if await User.exists(name=name):
                raise ValueError('用户已存在！')
            if not re.match(r'^1[3-9]\d{9}$', str(phone)):
                raise ValueError('手机号码格式错误！')
            if await User.exists(phone=str(name)):
                raise ValueError('手机号码已经存在了！')

            # 将有效数据保存到数据库中，这里假设有一个数据库操作函数 save_user()
            await User.create(name=name, nick_name=nick_name, phone=phone, password=hash_password(str(password)))
        except ValueError as e:
            print(f"数据导入失败：{e}")

    return base_response(code=200, msg='导入用户成功！')
